-- /*
--  * @Descripttion: 
--  * @version: 
--  * @Author: jiuguo.qin
--  * @Date: 2020-05-05 15:30:12
--  * @LastEditors: jiuguo.qin
--  * @LastEditTime: 2020-05-05 15:30:52
--  */
local http2tcp = require "http2tcp"
local cjson = require "cjson"
local _M = {
    _VERSION = 0.1
}

function _M:new()
    self.__index = self

    local mysql = require("resty.mysql")  
    local db, err = mysql:new()  
    if not db then  
        print("new mysql error : ", err)  
        return  
    end  

    db:set_timeout(1000)  
    local props = {  
        host = "127.0.0.1",  
        port = 3306,  
        database = "att",  
        user = "root",  
        password = "Lzslov123!"
    }  
    
    local res, err, errno, sqlstate = db:connect(props)  
    if not res then
        print("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
        return
    end

    self.db = db
    return _M
end


function _M:db_query(sql)
    local res, err, errno, sqlstate = self.db:query(sql)
    if not res then 
        print("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
        return
    end

    -- local times, err = self.db:get_reused_times()
    -- print("times = ", times)
    -- local ok, err = self.db:set_keepalive(10000, 100)
    -- if not ok then
    --     print("failed to set keepalive: ", err)
    -- end

    return res
end

function _M:save(record)
    local sql = string.format([[
            insert into wrk_metric_tab set 
            task_id=%s,
            target='%s',
            metric_name='%s',
            metric_value=%s,
            timestamp_ms=%s,
            ctime=Now()
        ]], record.taskid, record.target, record.metric_name, record.metric_value, os.time()*1000)
    
    self:db_query(sql)
end


function _M:save_detail_metric(taskid, detail)
    local metric = {"qps", "connections", "latency", "err_biz", "err_read", "err_connect", "err_status", "err_timeout", "err_write", "requests"}
    for path, item in pairs(detail) do 
        for _, metric_name in pairs(metric) do 
            local new_value = item[metric_name] or 0
            local record = {
                taskid = taskid, 
                target = path,
                metric_name = metric_name,
                metric_value = new_value
            }
            self:save(record)
        end
    end
end

function _M:save_overview_metric(taskid, overview)
    local metric = {"RecvRate", "SendRate", "TotalSendBytes",  "TotalRecvBytes", "Runtime", "TotalRequests", "TotalCompletes"}
    for _, metric_name in pairs(metric) do 
        local new_value = overview[metric_name] or 0
        local record = {
            taskid = taskid, 
            target = "over-view",
            metric_name = metric_name,
            metric_value = new_value
        }
        self:save(record)
    end

    for k, v in pairs(overview.errors) do 
        local record = {
            taskid = taskid, 
            target = "over-view",
            metric_name = string.format("Err-%s", k),
            metric_value = v
        }
        self:save(record)
    end
end

function _M:update_taks_status(taskid, status)
    local sql = string.format("update wrk_task_tab set status='%s' where id=%s", status, taskid)
    print(sql)
    self:db_query(sql)
end

function _M:get_running_taskids()
    local sql = "select id from wrk_task_tab where status='running'"
    return self:db_query(sql)
end


function _M:handler()
    local task_ids = self:get_running_taskids()
    -- print(cjson.encode(task_ids))
    for _, v in pairs(task_ids) do 
        local taskid = tonumber(v.id)
        http2tcp:new("127.0.0.1", 9877)
        local cmd    = "stats"
        local is_force = 0
        local body = ""
        http2tcp:send({taskid=taskid, is_force=0, command=cmd, payload=body})
        local data = http2tcp:receive()
        if data.stop ==1 then 
            self:update_taks_status(taskid, "stop")
        end

        self:save_detail_metric(taskid, data.detail)
        self:save_overview_metric(taskid, data.overview)
        -- save_percent_metric(db, taskid, data.percent)
    end
end

return _M